//
//  HMRefreshControl.swift
//  Weibo
//
//  Created by Apple on 2017/7/15.
//  Copyright © 2017年 KY. All rights reserved.
//

import UIKit
//  自定义下拉刷新控件的高度
private let HMRefreshControlHeight: CGFloat = 50

//  下拉刷新的三种状态
enum HMRefreshControlType {
    case normal
    case pulling
    case refreshing
}

//  自定义下拉刷新
class HMRefreshControl: UIControl {

    //  当前控件的刷新状态
    var refreshType: HMRefreshControlType = .normal {
        didSet {
            switch refreshType {
            case .normal:
                print("normal")
                //  显示箭头，箭头重置，停止风火轮，文字改成下拉刷新
                iconImageView.isHidden = false
                indicatorView.stopAnimating()
                UIView.animate(withDuration: 0.25, animations: { 
                    self.iconImageView.transform = CGAffineTransform.identity
                }, completion: { (_) in
                    if oldValue == .refreshing {
                        UIView.animate(withDuration: 0.25, animations: {
                            self.currentScrollView?.contentInset.top -= HMRefreshControlHeight
                        })
                    }
                })
                messageLabel.text = "下拉刷新"
                
                
            case .pulling:
                print("pulling")
                //  箭头调转，文字改成松手就刷新in
                UIView.animate(withDuration: 0.25, animations: { 
                    self.iconImageView.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
                })
                messageLabel.text = "松手就刷新"
            case .refreshing:
                print("refreshing")
                //  隐藏箭头，开启风火轮，文字改成正在刷新
                iconImageView.isHidden = true
                indicatorView.startAnimating()
                messageLabel.text = "正在刷新..."
                //  设置停留
                UIView.animate(withDuration: 0.25, animations: { 
                    self.currentScrollView?.contentInset.top += HMRefreshControlHeight
                }, completion: { (_) in
                    //  发送事件
                    self.sendActions(for: .valueChanged)
                })
            }
        }
    }
    //  当前滚动视图
    var currentScrollView: UIScrollView?
    
    //  MARK:   --懒加载控件
    fileprivate lazy var iconImageView: UIImageView = UIImageView(image: UIImage(named: "tableview_pull_refresh"))
    fileprivate lazy var indicatorView: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
    fileprivate lazy var messageLabel: UILabel = {
        let label = UILabel()
        label.text = "下拉刷新"
        label.font = UIFont.systemFont(ofSize: 12)
        label.textColor = UIColor.gray
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    //  添加控件设置约束
    private func setupUI() {
        backgroundColor = UIColor.red
        
        //  手写代码进行自动布局
        iconImageView.translatesAutoresizingMaskIntoConstraints = false
        indicatorView.translatesAutoresizingMaskIntoConstraints = false
        messageLabel.translatesAutoresizingMaskIntoConstraints = false
        
        addSubview(iconImageView)
        addSubview(indicatorView)
        addSubview(messageLabel)
        
        addConstraint(NSLayoutConstraint(item: iconImageView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: -35))
        addConstraint(NSLayoutConstraint(item: iconImageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: indicatorView, attribute: .centerX, relatedBy: .equal, toItem: iconImageView, attribute: .centerX, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: indicatorView, attribute: .centerY, relatedBy: .equal, toItem: iconImageView, attribute: .centerY, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .centerY, relatedBy: .equal, toItem: iconImageView, attribute: .centerY, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .leading, relatedBy: .equal, toItem: iconImageView, attribute: .trailing, multiplier: 1, constant: 0))
        
    }
    
    //  获取滚动视图，使用kvo监听其滚动
    override func willMove(toSuperview newSuperview: UIView?) {
        //  判断是否是滚动视图
        guard let scrollView = newSuperview as? UIScrollView else {
            return
        }
        self.frame = CGRect(x: 0, y: -HMRefreshControlHeight, width: scrollView.frame.size.width, height: HMRefreshControlHeight)
        //  使用kvo监听其滚动
        scrollView.addObserver(self, forKeyPath: "contentOffset", options: .new, context: nil)
        currentScrollView = scrollView
    }
    
    //  kvo监听方法
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        //  滚动偏移量
        let contentOffsetY = currentScrollView!.contentOffset.y
        
        //  刷新状态细分，可以分为在拖动情况下只有normal和pulling，松手情况下并且当前状态是pulling状态才能进入refreshing状态
        if currentScrollView!.isDragging {
            //  拖动
            //  计算拖动情况下的临界点
            let limitY = -(currentScrollView!.contentInset.top + HMRefreshControlHeight)
            if contentOffsetY < limitY && refreshType == .normal {
                //  pulling
                refreshType = .pulling
                print("pulling")
            } else if contentOffsetY >= limitY && refreshType == .pulling {
                //  normal
                refreshType = .normal
                print("normal")
            }
            
        } else {
            //  松手
            if refreshType == .pulling {
                refreshType = .refreshing
            }
            
        }
        
        
    }
    
    //  结束刷新
    func endRefreshing() {
        refreshType = .normal
    }
    
    deinit {
        //  移除kvo
        currentScrollView?.removeObserver(self, forKeyPath: "contentOffset")
    }

}
